package com.zhibang.config.security;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.zhibang.entity.Users;
import com.zhibang.util.JwtUtil;
import com.zhibang.util.Result;
import jakarta.annotation.Resource;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

/**
 * 安全令牌过滤器，用于处理用户请求的令牌验证
 */
@Component
public class SecurityTokenFilter extends OncePerRequestFilter {
    @Resource
    RedisTemplate<String,Object> redisTemplate;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        // 从请求头中获取JWT令牌
        String token = request.getHeader("token");
        // 如果是登录 或者 没有令牌 就放行
        if(StringUtils.isBlank(token) || request.getServletPath().equals("/login")){
            filterChain.doFilter(request, response);
            return;
        }
        // 设置服务器响应类型
        response.setContentType("application/json;charset=UTF-8");
        // 验证令牌是否合法
        if(!JwtUtil.validateToken(token)){
            String str = JSON.toJSONString(Result.fail("令牌不合法"));
            response.getWriter().write(str);
            return;
        }
        // 验证令牌(会话)是否过期
        Users user = (Users) redisTemplate.opsForValue().get("token:"+token);
        if(user == null){
            String str = JSON.toJSONString(Result.fail(1002,"会话已过期,请重新登录"));
            response.getWriter().write(str);
            return;
        }
        // 会话续期 30min
        redisTemplate.expire("token:"+token,30, TimeUnit.MINUTES);
        // 把用户信息放入上下文
        UsernamePasswordAuthenticationToken auth =
                new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(auth);
        // 继续过滤链
        filterChain.doFilter(request, response);
    }
}